#!/usr/bin/env python
# -*- coding:utf-8 -*-

import datetime
import math
import json

from sqlalchemy import or_

from app import db
from models.appointment_info import AppointmentInfo
from utils import commons
from utils.response_code import RET, error_map_EN
from utils.loggings import loggings
from models import BaseModel
from service.appointmentInfoService import AppointmentInfoService
from controller.scheduleController import ScheduleController


class AppointmentInfoController(AppointmentInfo,BaseModel):

    # add
    @classmethod
    def add(cls, **kwargs):
        from utils.generate_id import GenerateID
        record_id = GenerateID.create_random_id()
        
        try:
            model = AppointmentInfo(
                record_id=record_id,
                client_id=kwargs.get('client_id'),
                counselor_id=kwargs.get('counselor_id'),
                time_id=kwargs.get('time_id'),
                appointment_status=kwargs.get('appointment_status'),
                cancel_reason=kwargs.get('cancel_reason'),
                request_time=kwargs.get('request_time'),
                remark=kwargs.get('remark'),
                create_time=kwargs.get('create_time'),
                update_time=kwargs.get('update_time')
            )
            db.session.add(model)
            db.session.commit()
            results = {
                'add_time': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                'record_id': model.record_id
            }
            return {'code': RET.OK, 'message': error_map_EN[RET.OK], 'data': results}
            
        except Exception as e:
            db.session.rollback()
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': error_map_EN[RET.DBERR], 'data': {'error': str(e)}}
        finally:
            db.session.close()

    # get
    @classmethod
    def get(cls, **kwargs):
        try:
            filter_list = [cls.is_delete == 0]
            if kwargs.get('record_id'):
                filter_list.append(cls.record_id == kwargs['record_id'])
            else:
                if kwargs.get('client_id') is not None:
                    filter_list.append(cls.client_id == kwargs.get('client_id'))
                if kwargs.get('counselor_id') is not None:
                    filter_list.append(cls.counselor_id == kwargs.get('counselor_id'))
                if kwargs.get('time_id') is not None:
                    filter_list.append(cls.time_id == kwargs.get('time_id'))
                if kwargs.get('appointment_status') is not None:
                    filter_list.append(cls.appointment_status == kwargs.get('appointment_status'))
                if kwargs.get('cancel_reason'):
                    filter_list.append(cls.cancel_reason == kwargs.get('cancel_reason'))
                if kwargs.get('request_time'):
                    filter_list.append(cls.request_time == kwargs.get('request_time'))
                if kwargs.get('remark'):
                    filter_list.append(cls.remark == kwargs.get('remark'))
                if kwargs.get('create_time'):
                    filter_list.append(cls.create_time == kwargs.get('create_time'))
                if kwargs.get('update_time'):
                    filter_list.append(cls.update_time == kwargs.get('update_time'))
                

            page = int(kwargs.get('Page', 1))
            size = int(kwargs.get('Size', 10))
            
            appointment_info_info = db.session.query(cls).filter(*filter_list)
            
            count = appointment_info_info.count()
            pages = math.ceil(count / size)
            appointment_info_info = appointment_info_info.limit(size).offset((page - 1) * size).all()
   
            #results = commons.query_to_dict(appointment_info_info)
            results = cls.to_dict(appointment_info_info)
            # 在返回结果前过滤字段
            filtered_results = cls.filter_fields(results)
            return {
                'code': RET.OK, 
                'message': error_map_EN[RET.OK], 
                'totalCount': count, 
                'totalPage': pages, 
                'data': filtered_results
            }
            
        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': error_map_EN[RET.DBERR], 'data': {'error': str(e)}}
        finally:
            db.session.close()

    # delete
    @classmethod
    def delete(cls, **kwargs):
        try:
            filter_list = [cls.is_delete == 0]
            if kwargs.get('record_id'):
                primary_key_list = []
                for primary_key in str(kwargs.get('record_id')).replace(' ', '').split(','):
                    primary_key_list.append(cls.record_id == primary_key)
                filter_list.append(or_(*primary_key_list))
                
            else:
                if kwargs.get('client_id') is not None:
                    filter_list.append(cls.client_id == kwargs.get('client_id'))
                if kwargs.get('counselor_id') is not None:
                    filter_list.append(cls.counselor_id == kwargs.get('counselor_id'))
                if kwargs.get('time_id') is not None:
                    filter_list.append(cls.time_id == kwargs.get('time_id'))
                if kwargs.get('appointment_status') is not None:
                    filter_list.append(cls.appointment_status == kwargs.get('appointment_status'))
                if kwargs.get('cancel_reason'):
                    filter_list.append(cls.cancel_reason == kwargs.get('cancel_reason'))
                if kwargs.get('request_time'):
                    filter_list.append(cls.request_time == kwargs.get('request_time'))
                if kwargs.get('remark'):
                    filter_list.append(cls.remark == kwargs.get('remark'))
                if kwargs.get('create_time'):
                    filter_list.append(cls.create_time == kwargs.get('create_time'))
                if kwargs.get('update_time'):
                    filter_list.append(cls.update_time == kwargs.get('update_time'))
                
            res = db.session.query(cls).filter(*filter_list).with_for_update()

            results = {
                'delete_time': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                'record_id': []
            }
            for query_model in res.all():
                results['record_id'].append(query_model.record_id)

            res.update({'is_delete': 1})
            db.session.commit()

            return {'code': RET.OK, 'message': error_map_EN[RET.OK], 'data': results}

        except Exception as e:
            db.session.rollback()
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': error_map_EN[RET.DBERR], 'data': {'error': str(e)}}
        finally:
            db.session.close()
    
    # update
    @classmethod
    def update(cls, **kwargs):
        try:
            if 'appointment_status' in kwargs :
                return AppointmentInfoService.handle_appointment_status_change(
                    record_id=kwargs.get('record_id'),
                    new_status=kwargs.get('appointment_status'),
                    appointment_controller=cls,
                    schedule_controller=ScheduleController
                )
            
            # 其他普通更新操作保持不变
            filter_list = [cls.is_delete == 0]
            filter_list.append(cls.record_id == kwargs.get('record_id'))

            res = db.session.query(cls).filter(*filter_list).with_for_update()
            if res.first():
                results = {
                    'update_time': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                    'record_id': res.first().record_id,
                }
                
                res.update(kwargs)
                db.session.commit()
            else:
                results = {
                    'error': 'data dose not exist'
                }

            return {'code': RET.OK, 'message': error_map_EN[RET.OK], 'data': results}

        except Exception as e:
            db.session.rollback()
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': error_map_EN[RET.DBERR], 'data': {'error': str(e)}}
        finally:
            db.session.close()

    # batch add
    @classmethod
    def add_list(cls, **kwargs):
        param_list = kwargs.get('AppointmentInfoList')
        model_list = []
        for param_dict in param_list:
            from utils.generate_id import GenerateID
            record_id = GenerateID.create_random_id()
            
            model = AppointmentInfo(
                record_id=record_id,
                client_id=param_dict.get('client_id'),
                counselor_id=param_dict.get('counselor_id'),
                time_id=param_dict.get('time_id'),
                appointment_status=param_dict.get('appointment_status'),
                cancel_reason=param_dict.get('cancel_reason'),
                request_time=param_dict.get('request_time'),
                remark=param_dict.get('remark'),
                create_time=param_dict.get('create_time'),
                update_time=param_dict.get('update_time'),
                
            )
            model_list.append(model)
        
        try:
            db.session.add_all(model_list)
            db.session.commit()
            results = {
                'added_records': [],
                'add_time': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }
            for model in model_list:
                added_record = {}
                added_record['record_id'] = model.record_id
                
                results['added_records'].append(added_record)
                
            return {'code': RET.OK, 'message': error_map_EN[RET.OK], 'data': results}
            
        except Exception as e:
            db.session.rollback()
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': error_map_EN[RET.DBERR], 'data': {'error': str(e)}}
        finally:
            db.session.close()

    @classmethod
    def update_status(cls, record_id, appointment_status, cancel_reason=None):
        """单独处理状态更新的方法"""
        try:
            filter_list = [cls.is_delete == 0, cls.record_id == record_id]
            update_data = {'appointment_status': appointment_status}
            if cancel_reason:
                update_data['cancel_reason'] = cancel_reason
                
            res = db.session.query(cls).filter(*filter_list).with_for_update()
            if res.first():
                res.update(update_data)
                db.session.commit()
                results = {
                    'update_time': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                    'record_id': record_id
                }
                return {'code': RET.OK, 'message': error_map_EN[RET.OK], 'data': results}
            return {'code': RET.NODATA, 'message': error_map_EN[RET.NODATA], 'data': None}
        except Exception as e:
            db.session.rollback()
            return {'code': RET.DBERR, 'message': error_map_EN[RET.DBERR], 'data': {'error': str(e)}}

    @classmethod
    def filter_fields(cls, data_list):
        """过滤并只返回指定的字段"""
        filtered_list = []
        desired_fields = [
            'record_id', 
            'client_id', 
            'counselor_id', 
            'time_id', 
            'appointment_status', 
            'cancel_reason', 
            'request_time', 
            'remark',
            'is_delete'
        ]
        
        for item in data_list:
            filtered_item = {k: item[k] for k in desired_fields if k in item}
            filtered_list.append(filtered_item)
        
        return filtered_list
